﻿/*
Copyright 2009 Matías Fidemraizer (www.matiasfidemraizer.com).

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

using System;

using Comkarl.Architecture.Patterns.MVC.Entities;

namespace Comkarl
{
    /// <summary>
    /// Represents an identifier of some type.
    /// </summary>
    /// <typeparam name="TIdentifierName">
    /// The type of current.
    /// </typeparam>
    public abstract class Identifier<TIdentifierName> : IEquatable<Identifier<TIdentifierName>> 
        where TIdentifierName : IEquatable<TIdentifierName>
    {
        #region "Fields"
        /// <summary>
        /// Retrieves the name of the identifier.
        /// </summary>
        private readonly TIdentifierName name;
        #endregion

        #region "Constructors"
        /// <summary>
        /// Default constructor
        /// </summary>
        /// <param name="name">
        /// Sets the name for the on-going identifier.
        /// </param>
        public Identifier(TIdentifierName name)
        {
            if (name == null || name.ToString().Length == 0)
            {
                throw new IdentifierNameNullException<TIdentifierName>(this, new ArgumentNullException("name", "Identifier name cannot be null or empty."));
            }

            this.name = name;
        }

        private Identifier()
        {
        }
        #endregion

        #region "Properties"
        /// <summary>
        /// Gets the current identifier's name.
        /// </summary>
        public TIdentifierName Name
        {
            get
            {
                return name;
            }
        }
        #endregion

        #region "Static methods"
        public static void Validate(Identifier<TIdentifierName> someId)
        {
            // The unique identifier cannot be null and its name cannot be null or empty.
            if (someId == null)
            {
                throw new IdentifierNullException<TIdentifierName>(new ArgumentNullException("someId"));
            }
        }
        #endregion

        #region Operators
        public static implicit operator string(Identifier<TIdentifierName> input)
        {
            return input.ToString();
        }
        #endregion

        #region "Overriden methods"
        /// <summary>
        /// Overrides the Object.ToString to serialize current action to string with the assigned name.
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return Name.ToString();
        }

        public override bool Equals(object obj)
        {
            return obj != null && obj.GetType() == typeof(Identifier<TIdentifierName>) && Name.Equals(((Identifier<TIdentifierName>)obj).Name);
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
        #endregion

        #region IEquatable<Identifier<TIdentifierName>> Members

        public bool Equals(Identifier<TIdentifierName> other)
        {
            return other != null && Name.Equals(other.Name);
        }

        #endregion
    }
}
